package com.shiwaixiangcun.monitor.service.impl;

import com.rabbit.spring.data.search.SearchOperator;
import com.rabbit.spring.data.search.Searchable;
import com.rabbit.spring.data.search.filter.SearchFilter;
import com.rabbit.spring.data.search.filter.SearchFilterHelper;
import com.shiwaixiangcun.core.domain.Dictionary;
import com.shiwaixiangcun.core.exceptions.MonkeyException;
import com.shiwaixiangcun.core.plugin.dto.MonkeyDto;
import com.shiwaixiangcun.core.repository.dictionary.DictionaryRepository;
import com.shiwaixiangcun.core.service.BaseServiceImpl;
import com.shiwaixiangcun.core.utils.MonkeyUtils;
import com.shiwaixiangcun.monitor.domain.Device;
import com.shiwaixiangcun.monitor.dto.DeviceDetailsDto;
import com.shiwaixiangcun.monitor.dto.DeviceListDto;
import com.shiwaixiangcun.monitor.dto.DeviceSearchDto;
import com.shiwaixiangcun.monitor.dto.WirelessReceiverListDto;
import com.shiwaixiangcun.monitor.enums.DeviceBrand;
import com.shiwaixiangcun.monitor.enums.DeviceType;
import com.shiwaixiangcun.monitor.repository.DeviceRepository;
import com.shiwaixiangcun.monitor.service.DeviceService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2018-01-15.
 */
@Service
@Transactional
public class DeviceServiceImpl extends BaseServiceImpl<Device, Long> implements DeviceService {

    @Autowired
    private DeviceRepository deviceRepository;
    @Autowired
    private DictionaryRepository dictionaryRepository;

    @Override
    public void saveDevice(MonkeyDto monkeyDto) {
        Device device = new Device();
        buildDevice(device, monkeyDto);
        deviceRepository.save(device);
    }

    @Override
    public void updateDevice(MonkeyDto monkeyDto) {
        Long id = monkeyDto.getLong("id");
        Device device = deviceRepository.findOne(id);
        if (MonkeyUtils.isNotEmpty(device)) {
            buildDevice(device, monkeyDto);
            deviceRepository.save(device);
        }
    }

    @Override
    public DeviceDetailsDto getDeviceDetails(Long id) {
        Device device = deviceRepository.findOne(id);
        DeviceDetailsDto deviceDetailsDto = new DeviceDetailsDto();
        if (MonkeyUtils.isNotEmpty(device)) {
            BeanUtils.copyProperties(device, deviceDetailsDto);
            Long belongToReceiver = deviceDetailsDto.getBelongToReceiver();
            if (MonkeyUtils.isNotEmpty(belongToReceiver)) {
                Device one = deviceRepository.findOne(belongToReceiver);
                deviceDetailsDto.setBelongToReceiverName(one.getName());
            }
            deviceDetailsDto.setModelId(device.getModel().getId());
            deviceDetailsDto.setModel(device.getModel().getName());
            deviceDetailsDto.setCreateTime(device.getCreateTime());
            deviceDetailsDto.setId(id);
        }
        return deviceDetailsDto;
    }

    @Override
    public Page<DeviceListDto> getDeviceList(Pageable pageable, DeviceSearchDto deviceSearchDto) {
        Searchable searchable = Searchable.newSearchable();
        searchable.setPage(pageable);
        if (MonkeyUtils.isNotEmpty(deviceSearchDto.getSearch())) {
            String search = deviceSearchDto.getSearch();
            SearchFilter f1 = SearchFilterHelper.newCondition("number", SearchOperator.like, "%" + search + "%");
            SearchFilter f2 = SearchFilterHelper.newCondition("name", SearchOperator.like, "%" + search + "%");
            searchable.or(f1, f2);
        }
        if (MonkeyUtils.isNotEmpty(deviceSearchDto.getDeviceBrand())) {
            searchable.addSearchFilter("deviceBrand", SearchOperator.eq, deviceSearchDto.getDeviceBrand());
        }
        if (MonkeyUtils.isNotEmpty(deviceSearchDto.getDeviceType())) {
            searchable.addSearchFilter("deviceType", SearchOperator.eq, deviceSearchDto.getDeviceType());
        }
        if (MonkeyUtils.isNotEmpty(deviceSearchDto.getModelId())) {
            Dictionary dictionary = dictionaryRepository.findOne(deviceSearchDto.getModelId());
            searchable.addSearchFilter("model", SearchOperator.eq, dictionary);
        }
        searchable.addSort(new Sort(Sort.Direction.DESC, "id"));
        Page<Device> all = deviceRepository.findAll(searchable);
        List<Device> deviceList = all.getContent();
        List<DeviceListDto> deviceListDto = new ArrayList<>();
        buildDevicePageList(deviceList, deviceListDto);
        return new PageImpl<>(deviceListDto, pageable, all.getTotalElements());
    }

    @Override
    public List<WirelessReceiverListDto> getWirelessReceiverList() {
        Searchable searchable = Searchable.newSearchable();
        searchable.addSearchFilter("deviceType", SearchOperator.eq, DeviceType.WirelessReceiver);
        List<Device> deviceList = deviceRepository.findAll(searchable).getContent();
        List<WirelessReceiverListDto> wirelessReceiverListDto = new ArrayList<>();
        buildDeviceList(deviceList, wirelessReceiverListDto);
        return wirelessReceiverListDto;
    }

    private void buildDeviceList(List<Device> deviceList, List<WirelessReceiverListDto> wirelessReceiverListDto) {
        for (Device device : deviceList) {
            WirelessReceiverListDto wirelessReceiverList = new WirelessReceiverListDto();
            wirelessReceiverList.setId(device.getId());
            wirelessReceiverList.setName(device.getName());
            wirelessReceiverListDto.add(wirelessReceiverList);
        }
    }

    private void buildDevicePageList(List<Device> deviceList, List<DeviceListDto> deviceListDto) {
        for (Device device : deviceList) {
            DeviceListDto listDto = new DeviceListDto();
            listDto.setId(device.getId());
            listDto.setName(device.getName());
            listDto.setNumber(device.getNumber());
            listDto.setDeviceBrand(device.getDeviceBrand().getLabel());
            listDto.setDeviceType(device.getDeviceType());
            listDto.setModel(device.getModel().getName());
            deviceListDto.add(listDto);
        }
    }

    private void buildDevice(Device device, MonkeyDto monkeyDto) {
        String number = monkeyDto.getString("number");
        if (MonkeyUtils.isNotEmpty(number)) {
            if (!number.equals(device.getNumber())) {
                Device deviceRepositoryByNumber = deviceRepository.findByNumber(number);
                if (MonkeyUtils.isNotEmpty(deviceRepositoryByNumber)) {
                    throw new MonkeyException("设备编号已经被使用");
                }
            }
            device.setNumber(number);
        }
        String name = monkeyDto.getString("name");
        if (MonkeyUtils.isNotEmpty(name)) {
            device.setName(name);
        }
        String longitude = monkeyDto.getString("longitude");
        String latitude = monkeyDto.getString("latitude");
        if (MonkeyUtils.isNotEmpty(longitude) && MonkeyUtils.isNotEmpty(latitude)) {
            device.setLatitude(latitude);
            device.setLongitude(longitude);
        }
        Long modelId = monkeyDto.getLong("modelId");
        if (MonkeyUtils.isNotEmpty(modelId)) {
            Dictionary dictionary = dictionaryRepository.findOne(modelId);
            device.setModel(dictionary);
        }
        String deviceType = monkeyDto.getString("deviceType");
        if (MonkeyUtils.isNotEmpty(deviceType)) {
            device.setDeviceType(DeviceType.valueOf(deviceType));
        }
        String deviceBrand = monkeyDto.getString("deviceBrand");
        if (MonkeyUtils.isNotEmpty(deviceBrand)) {
            device.setDeviceBrand(DeviceBrand.valueOf(deviceBrand));
        }
        Long belongToReceiver = monkeyDto.getLong("belongToReceiver");
        if (MonkeyUtils.isNotEmpty(belongToReceiver)) {
            device.setBelongToReceiver(belongToReceiver);
        }
    }
}
